package com.clientAda4j;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSON;
import com.clientAda4j.component.AnnotationPointCut;
import com.clientAda4j.component.ProfileEnvironment;
import com.clientAda4j.domain.ClientResponseProp;
import com.clientAda4j.exeption.ClientAdaExecuteException;
import com.clientAda4j.utils.ExecutorBuilder;
import com.google.common.collect.ImmutableMap;
import org.apache.http.entity.StringEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.LinkedHashMap;
import java.util.Objects;

/**
 * 请求执行器
 *
 * @author wanghe
 */
@Component
public class ClientAdaClaimExecutor implements Executor {
    private final AnnotationPointCut executor;
    private final ExecutorBuilder builder;

    @Autowired
    public ClientAdaClaimExecutor(AnnotationPointCut executor) {
        this.executor = executor;
        this.builder = this.executor.getExecutorBuilder();
    }

    /**
     * 基于响应工厂的执行
     *
     * @param args 参数
     * @return ClientResponseProp<LinkedHashMap < String, Object>>
     */
    @Override
    public ClientResponseProp<?> executeResponseFactory(Object args) {
        try {
            if (Objects.isNull(this.builder.getResponseFactory())) {
                throw new ClientAdaExecuteException("[ClientAda SDK] 基于响应工厂的执行函数，必须配置在注解@ClientAdaInterface中配置responseFactory");
            }
            return this.builder.getDefaultClientInterfaceControllerAda()
                    .addClientHeadersAdapter(this.builder.getClientHeaderAdapter().newInstance()).request(this.builder.getClientAdaCoreProp(), new StringEntity(JSON.toJSONString(args)), builder.getResponseFactory().newInstance());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 自定义执行
     *
     * @param args        参数
     * @param responseCls class
     * @return ClientResponseProp<LinkedHashMap < String, Object>>
     */

    @Override
    public <E> ClientResponseProp<E> executeResponseCls(Object args, Class<E> responseCls) {
        return this.executeResponseCls(args, responseCls, this.getExecutorBuilder());
    }

    /**
     * 自定义执行
     *
     * @param args        参数
     * @param responseCls responseCls
     * @param environment 环境处理器接口
     * @return ClientResponseProp<LinkedHashMap < String, Object>>
     */
    @Override
    public <E> ClientResponseProp<E> executeResponseCls(Object args, Class<E> responseCls, ProfileEnvironment environment) {
        if (Objects.nonNull(environment)) {
            this.builder.getClientAdaCoreProp().setClientUri(environment.resetClientUri());
        }
        return this.executeResponseCls(args, responseCls, this.getExecutorBuilder());
    }

    /**
     * 自定义执行可直接请求的API
     *
     * @param domainUrl 主请求地址
     * @param args      请求参数
     * @param method    请求方式(GET,POST,PUT,DELETE)
     * @return ClientResponseProp<LinkedHashMap < String, Object>>
     */
    @Override
    public ClientResponseProp<LinkedHashMap<String, Object>> execute(String domainUrl, ImmutableMap<String, Object> args, RequestMethod method) {
        try {
            return builder.getDefaultClientInterfaceControllerAda()
                    .addClientHeadersAdapter(builder.getClientHeaderAdapter().newInstance()).request(domainUrl, "", args, method);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 自定义执行可直接请求的API
     *
     * @param domainUrl   主请求地址
     * @param args        请求参数
     * @param responseCls 指定返回实体
     * @param method      请求方式(GET,POST,PUT,DELETE)
     * @return ClientResponseProp<LinkedHashMap < String, Object>>
     */
    @Override
    public <E> ClientResponseProp<E> execute(String domainUrl, ImmutableMap<String, Object> args, RequestMethod method, Class<E> responseCls) {
        return new ClientResponseProp<E>(BeanUtil.toBean(this.execute(domainUrl, args, method), responseCls));
    }


    private <E> ClientResponseProp<E> executeResponseCls(Object args, Class<E> responseCls, ExecutorBuilder builder) {
        try {
            return builder.getDefaultClientInterfaceControllerAda()
                    .addClientHeadersAdapter(builder.getClientHeaderAdapter().newInstance()).request(builder.getClientAdaCoreProp(), new StringEntity(JSON.toJSONString(args)), responseCls);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    private ExecutorBuilder getExecutorBuilder() {
        return this.executor.getExecutorBuilder();
    }

}